#include "Expand/Plugins/PlayerPlugin.h"
#include "Player/PlayerData.h"
#include "Subsystems/SubsystemPlayers.h"
#include "Log.h"
#include "sstream"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentHealth.h"
#include "Components/ComponentCreativeInventory.h"
#include "Components/ComponentInventory.h"
#include "Components/ComponentClothing.h"
#include "Components/ComponentBody.h"
#include "ServerConfigure.h"

#include "GameSingleton.h"
#include "Network/Client.h"

namespace PocketSurvival
{
    const std::string &PlayerPlugin::getPluginName()
    {
        static const std::string pluginName = "基本服务器玩家操作插件";
        return pluginName;
    }

    const std::string &PlayerPlugin::getIntroduce()
    {
        static const std::string introduce = "\n/player help - 查看帮助\n/kick help - 查看帮助\n/kill help - 查看帮助";
        return introduce;
    }

    uint32_t PlayerPlugin::getUseAuthLevel()
    {
        return 100;
    }

    AuthDisplayType PlayerPlugin::getDisplayType()
    {
        return AuthDisplayType::Authority;
    }

    void PlayerPlugin::processCmd(ChatObj &chatObj, std::vector<std::string> &cmdDataVec)
    {
        if(cmdDataVec[0] == "/player")
        {
            if(cmdDataVec.size() == 1)
            {
                std::vector<std::shared_ptr<PlayerData>> playerVec;
                m_subsystemPlayers->getAllPlayerData(playerVec);
                std::stringstream ss;
                std::sort(playerVec.begin(), playerVec.end(), [](std::shared_ptr<PlayerData> &left, std::shared_ptr<PlayerData> &right) -> bool
                {
                    return left->client->clientID < right->client->clientID;
                });
                for(std::shared_ptr<PlayerData> &player : playerVec)
                {
                    ss << fmt::format("\n[{}][{}][{}][{}]{}",player->client->clientID, player->playerGuid.toString(), player->playerDataID, (uint16_t)player->entity, player->username);
                }
                chatObj.sendMessage("player", ss.str());
            }
            else
            {
                if(cmdDataVec.size() >= 3)
                {
                    if(cmdDataVec[1] == "user")
                    {
                        std::vector<std::shared_ptr<PlayerData>> playerVec;
                        m_subsystemPlayers->getPlayerDataByName(cmdDataVec[2], playerVec);
                        if(playerVec.size() == 0)
                        {
                            chatObj.sendMessage("player", fmt::format("玩家 {} 貌似不在线", cmdDataVec[2]));
                        }
                        else
                        {
                            std::stringstream ss;
                            for(std::shared_ptr<PlayerData> &playerData : playerVec)
                            {
                                Vector3 position;
                                playerData->componentPlayer->componentBody->getPosition(position);

                                ss << fmt::format("\n=====\n玩家: {}\nGuid: {}\nClientID: {}\naddress: {}\nPlayerGameMode: {}\nCreativeInventoryID: {}\nClothingInventoryID: {}\nInventoryID: {}\nHealth: {}\nInvincibleTime : {}\nPosition: {}\n=====",
                                    playerData->username, 
                                    playerData->playerGuid.toString(), 
                                    playerData->client->clientID, 
                                    playerData->client->getAddress(),
                                    (uint8_t)playerData->playerGameMode,
                                    playerData->componentPlayer->componentCreativeInventory->id,
                                    playerData->componentPlayer->componentClothing->id,
                                    playerData->componentPlayer->componentInventory->id,
                                    playerData->componentPlayer->componentHealth->health,
                                    playerData->componentPlayer->componentHealth->invincibleTime,
                                    position.toString());
                            }
                            chatObj.sendMessage("player", ss.str());
                        }
                        return;
                    }
                    else if(cmdDataVec[1] == "guid")
                    {
                        std::shared_ptr<PlayerData> targetPlayer = m_subsystemPlayers->getPlayerDataByGuid(GameGuid(cmdDataVec[2]));
                        if(targetPlayer != nullptr)
                        {
                            Vector3 position;
                            targetPlayer->componentPlayer->componentBody->getPosition(position);

                            chatObj.sendMessage("player", fmt::format("\n=====\n玩家: {}\nGuid: {}\nClientID: {}\naddress: {}\nPlayerGameMode: {}\nCreativeInventoryID: {}\nClothingInventoryID: {}\nInventoryID: {}\nHealth: {}\nInvincibleTime : {}\nPosition: {}\n=====",
                                targetPlayer->username, 
                                targetPlayer->playerGuid.toString(), 
                                targetPlayer->client->clientID, 
                                targetPlayer->client->getAddress(),
                                (uint8_t)targetPlayer->playerGameMode,
                                targetPlayer->componentPlayer->componentCreativeInventory->id,
                                targetPlayer->componentPlayer->componentClothing->id,
                                targetPlayer->componentPlayer->componentInventory->id,
                                targetPlayer->componentPlayer->componentHealth->health,
                                targetPlayer->componentPlayer->componentHealth->invincibleTime,
                                position.toString()));
                        }
                        else
                        {
                            chatObj.sendMessage("player", fmt::format("GUID为 {} 的玩家貌似不在线", cmdDataVec[2]));
                        }
                        return;
                    }
                    // 只有控制台能改人数
                    else if(cmdDataVec[1] == "max" && chatObj.m_isTerminal == true)
                    {
                        uint32_t maxPlayerCount = atoi(cmdDataVec[2].c_str());
                        GameSingleton::serverConfigure->maxPlayer = maxPlayerCount;
                        chatObj.sendMessage("player", fmt::format("服务器最大玩家数改为: {}", maxPlayerCount));
                        return;
                    }
                }
                chatObj.sendMessage("player", "\n/player - 显示玩家列表\n/player user (在线玩家) - 查看玩家的信息\n/player guid (在线玩家GUID) - 查看玩家的信息");
            }
            return;
        }



        if(cmdDataVec[0] == "/kick")
        {
            if(cmdDataVec.size() >= 3)
            {
                if(cmdDataVec[1] == "user")
                {
                    std::vector<std::shared_ptr<PlayerData>> playerVec;
                    m_subsystemPlayers->getPlayerDataByName(cmdDataVec[2], playerVec);
                    if(playerVec.size() == 0)
                    {
                        chatObj.sendMessage("kick", fmt::format("玩家 {} 貌似不在线", cmdDataVec[2]));
                    }
                    else
                    {
                        std::string cause = "你已经被踢出了服务器";
                        if(cmdDataVec.size() >= 4)
                        {
                            cause = cmdDataVec[3];
                        }
                        for(std::shared_ptr<PlayerData> &playerData : playerVec)
                        {
                            playerData->client->disconnect(cause);
                        }
                        chatObj.sendMessage("kick", fmt::format("成功踢出所有名字叫 {} 的玩家", cmdDataVec[2]));
                    }
                    return;
                }
                else if(cmdDataVec[1] == "guid")
                {
                    std::shared_ptr<PlayerData> targetPlayer = m_subsystemPlayers->getPlayerDataByGuid(GameGuid(cmdDataVec[2]));
                    if(targetPlayer != nullptr)
                    {
                        std::string cause = "你已经被踢出了服务器";
                        if(cmdDataVec.size() >= 4)
                        {
                            cause = cmdDataVec[3];
                        }
                        chatObj.sendMessage("kick", fmt::format("成功将 {} 踢出服务器", targetPlayer->username));
                    }
                    else
                    {
                        chatObj.sendMessage("kick", fmt::format("GUID为 {} 的玩家貌似不在线", cmdDataVec[2]));
                    }
                    return;
                }
            }
            chatObj.sendMessage("kick", "\n/kick user (在线玩家) (原因) - 踢出该玩家\n/kick guid (在线玩家GUID) (原因) - 踢出该玩家");
            return;
        }



        if(cmdDataVec[0] == "/kill")
        {
            if(cmdDataVec.size() >= 3)
            {
                if(cmdDataVec[1] == "user")
                {
                    std::vector<std::shared_ptr<PlayerData>> playerVec;
                    m_subsystemPlayers->getPlayerDataByName(cmdDataVec[2], playerVec);
                    if(playerVec.size() == 0)
                    {
                        chatObj.sendMessage("kill", fmt::format("玩家 {} 貌似不在线", cmdDataVec[2]));
                    }
                    else
                    {
                        std::string cause = "被幽灵死神带走了";
                        if(cmdDataVec.size() >= 4)
                        {
                            cause = cmdDataVec[3];
                        }
                        for(std::shared_ptr<PlayerData> &playerData : playerVec)
                        {
                            playerData->componentPlayer->componentHealth->injure(999.0f, entt::null, true, cause, InjureType::Plugin);
                        }
                        chatObj.sendMessage("kill", fmt::format("成功杀掉所有名字叫 {} 的玩家", cmdDataVec[2]));
                    }
                    return;
                }
                else if(cmdDataVec[1] == "guid")
                {
                    std::shared_ptr<PlayerData> targetPlayer = m_subsystemPlayers->getPlayerDataByGuid(GameGuid(cmdDataVec[2]));
                    if(targetPlayer != nullptr)
                    {
                        std::string cause = "被幽灵死神带走了";
                        if(cmdDataVec.size() >= 4)
                        {
                            cause = cmdDataVec[3];
                        }
                        targetPlayer->componentPlayer->componentHealth->injure(999.0f, entt::null, true, cause, InjureType::Plugin);
                        chatObj.sendMessage("kill", fmt::format("成功嘎掉了 {}", targetPlayer->username));
                    }
                    else
                    {
                        chatObj.sendMessage("kill", fmt::format("GUID为 {} 的玩家貌似不在线", cmdDataVec[2]));
                    }
                    return;
                }
            }
            chatObj.sendMessage("kill", "\n/kill user (在线玩家) (原因) - 杀掉该玩家\n/kill guid (在线玩家GUID) (原因) - 杀掉该玩家");
            return;
        }
    }

    void PlayerPlugin::getCmds(std::vector<std::string> &cmdVec)
    {
        cmdVec.push_back("/player");
        cmdVec.push_back("/kick");
        cmdVec.push_back("/kill");
    }

    void PlayerPlugin::load()
    {
        m_subsystemPlayers = GameSingleton::singletonPtr->getSingleton<SubsystemPlayers>();
    }

} // namespace PocketSurvival
